1 Functions

library(stringi)
library(reticulate)
library(ggplotify)

source_from_github(repositoy = "DEG_functions",version = "0.2.47")
ℹ SHA-1 hash of file is f5bb1cd741d13bded83fe3b6fd43169e29731216
Welcome to enrichR
Checking connection ... 
Enrichr ... Connection is Live!
FlyEnrichr ... Connection is available!
WormEnrichr ... Connection is available!
YeastEnrichr ... Connection is available!
FishEnrichr ... Connection is available!
source_from_github(repositoy = "cNMF_functions",version = "0.4.04",script_name = "cnmf_functions_V3.R")
ℹ SHA-1 hash of file is a735d9bfb5bc55fcb203f83a7240b9713fc080d3
source_from_github(repositoy = "sc_general_functions",version = "0.1.34",script_name = "functions.R")
ℹ SHA-1 hash of file is 55839fb7db3fdb3e61d8d423b0b3129bfa1d777b

2 Data

xeno <- qs::qread("./raw_data/xeno.qs")

3 DE pathways

pathwayScoresMatrix = read_rds(file = "./output_data/run_SiPSiC/pathwayScoresMatrix.RDS")
xeno[["sipsic"]] = CreateAssayObject(counts = pathwayScoresMatrix)
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
trace(Seurat:::FindMarkers.default,edit = T) #replace "bonferroni" with "fdr"
Warning in edit.default(def, editor = editor, file = file) :
  deparse may be incomplete
Tracing function "FindMarkers.default" in package "Seurat (not-exported)"
[1] "FindMarkers.default"
xeno = SetIdent(xeno, value = "treatment")
pathways_names = gsub(rownames(pathwayScoresMatrix), pattern = "_", replacement = "-")


logFC_df = data.frame(row.names = pathways_names)
fdr_df = data.frame(row.names = pathways_names)

for (model in unique(xeno$orig.ident)) {
  model_data = subset(xeno, subset = orig.ident == model)
  pathway_markers = FindMarkers(
    object = model_data,
    ident.1 = "OSI",
    ident.2 = "NT",
    assay = "sipsic",
    slot = "counts",
    logfc.threshold = 0,
    densify = T,
    pseudocount.use = 0.001,
    features = pathways_names
  )
  avg_log2FC = pathway_markers[pathways_names, "avg_log2FC", drop = F]
  colnames(avg_log2FC) = model
  pathway_markers  %<>%  dplyr::rename(fdr = p_val_adj)
  fdr = pathway_markers[pathways_names, "fdr", drop = F]
  colnames(fdr) = model
  
  logFC_df = cbind(logFC_df, avg_log2FC)
  fdr_df = cbind(fdr_df, fdr)
}

  |                                                  | 0 % ~calculating  
  |+                                                 | 2 % ~01s          
  |++                                                | 4 % ~01s          
  |+++                                               | 6 % ~01s          
  |++++                                              | 8 % ~01s          
  |+++++                                             | 10% ~01s          
  |++++++                                            | 12% ~01s          
  |+++++++                                           | 14% ~01s          
  |++++++++                                          | 16% ~00s          
  |+++++++++                                         | 18% ~00s          
  |++++++++++                                        | 20% ~00s          
  |+++++++++++                                       | 22% ~00s          
  |++++++++++++                                      | 24% ~00s          
  |+++++++++++++                                     | 26% ~00s          
  |++++++++++++++                                    | 28% ~00s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++                                  | 32% ~00s          
  |+++++++++++++++++                                 | 34% ~00s          
  |++++++++++++++++++                                | 36% ~00s          
  |+++++++++++++++++++                               | 38% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++                             | 42% ~00s          
  |++++++++++++++++++++++                            | 44% ~00s          
  |+++++++++++++++++++++++                           | 46% ~00s          
  |++++++++++++++++++++++++                          | 48% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++                        | 52% ~00s          
  |+++++++++++++++++++++++++++                       | 54% ~00s          
  |++++++++++++++++++++++++++++                      | 56% ~00s          
  |+++++++++++++++++++++++++++++                     | 58% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++                   | 62% ~00s          
  |++++++++++++++++++++++++++++++++                  | 64% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~00s          
  |++++++++++++++++++++++++++++++++++                | 68% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~00s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~00s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=00s  

  |                                                  | 0 % ~calculating  
  |+                                                 | 2 % ~01s          
  |++                                                | 4 % ~01s          
  |+++                                               | 6 % ~00s          
  |++++                                              | 8 % ~01s          
  |+++++                                             | 10% ~01s          
  |++++++                                            | 12% ~01s          
  |+++++++                                           | 14% ~01s          
  |++++++++                                          | 16% ~01s          
  |+++++++++                                         | 18% ~01s          
  |++++++++++                                        | 20% ~01s          
  |+++++++++++                                       | 22% ~01s          
  |++++++++++++                                      | 24% ~00s          
  |+++++++++++++                                     | 26% ~00s          
  |++++++++++++++                                    | 28% ~00s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++                                  | 32% ~00s          
  |+++++++++++++++++                                 | 34% ~00s          
  |++++++++++++++++++                                | 36% ~00s          
  |+++++++++++++++++++                               | 38% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++                             | 42% ~00s          
  |++++++++++++++++++++++                            | 44% ~00s          
  |+++++++++++++++++++++++                           | 46% ~00s          
  |++++++++++++++++++++++++                          | 48% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++                        | 52% ~00s          
  |+++++++++++++++++++++++++++                       | 54% ~00s          
  |++++++++++++++++++++++++++++                      | 56% ~00s          
  |+++++++++++++++++++++++++++++                     | 58% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++                   | 62% ~00s          
  |++++++++++++++++++++++++++++++++                  | 64% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~00s          
  |++++++++++++++++++++++++++++++++++                | 68% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~00s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~00s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s  

  |                                                  | 0 % ~calculating  
  |+                                                 | 2 % ~01s          
  |++                                                | 4 % ~01s          
  |+++                                               | 6 % ~01s          
  |++++                                              | 8 % ~01s          
  |+++++                                             | 10% ~01s          
  |++++++                                            | 12% ~01s          
  |+++++++                                           | 14% ~01s          
  |++++++++                                          | 16% ~01s          
  |+++++++++                                         | 18% ~01s          
  |++++++++++                                        | 20% ~00s          
  |+++++++++++                                       | 22% ~00s          
  |++++++++++++                                      | 24% ~00s          
  |+++++++++++++                                     | 26% ~00s          
  |++++++++++++++                                    | 28% ~00s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++                                  | 32% ~00s          
  |+++++++++++++++++                                 | 34% ~00s          
  |++++++++++++++++++                                | 36% ~00s          
  |+++++++++++++++++++                               | 38% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++                             | 42% ~00s          
  |++++++++++++++++++++++                            | 44% ~00s          
  |+++++++++++++++++++++++                           | 46% ~00s          
  |++++++++++++++++++++++++                          | 48% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++                        | 52% ~00s          
  |+++++++++++++++++++++++++++                       | 54% ~00s          
  |++++++++++++++++++++++++++++                      | 56% ~00s          
  |+++++++++++++++++++++++++++++                     | 58% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++                   | 62% ~00s          
  |++++++++++++++++++++++++++++++++                  | 64% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~00s          
  |++++++++++++++++++++++++++++++++++                | 68% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~00s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~00s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s  

  |                                                  | 0 % ~calculating  
  |+                                                 | 2 % ~01s          
  |++                                                | 4 % ~01s          
  |+++                                               | 6 % ~01s          
  |++++                                              | 8 % ~01s          
  |+++++                                             | 10% ~01s          
  |++++++                                            | 12% ~01s          
  |+++++++                                           | 14% ~01s          
  |++++++++                                          | 16% ~01s          
  |+++++++++                                         | 18% ~01s          
  |++++++++++                                        | 20% ~01s          
  |+++++++++++                                       | 22% ~01s          
  |++++++++++++                                      | 24% ~01s          
  |+++++++++++++                                     | 26% ~01s          
  |++++++++++++++                                    | 28% ~01s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++                                  | 32% ~00s          
  |+++++++++++++++++                                 | 34% ~00s          
  |++++++++++++++++++                                | 36% ~00s          
  |+++++++++++++++++++                               | 38% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++                             | 42% ~00s          
  |++++++++++++++++++++++                            | 44% ~00s          
  |+++++++++++++++++++++++                           | 46% ~00s          
  |++++++++++++++++++++++++                          | 48% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++                        | 52% ~00s          
  |+++++++++++++++++++++++++++                       | 54% ~00s          
  |++++++++++++++++++++++++++++                      | 56% ~00s          
  |+++++++++++++++++++++++++++++                     | 58% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++                   | 62% ~00s          
  |++++++++++++++++++++++++++++++++                  | 64% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~00s          
  |++++++++++++++++++++++++++++++++++                | 68% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~00s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~00s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s  

  |                                                  | 0 % ~calculating  
  |+                                                 | 2 % ~01s          
  |++                                                | 4 % ~01s          
  |+++                                               | 6 % ~01s          
  |++++                                              | 8 % ~01s          
  |+++++                                             | 10% ~01s          
  |++++++                                            | 12% ~01s          
  |+++++++                                           | 14% ~01s          
  |++++++++                                          | 16% ~01s          
  |+++++++++                                         | 18% ~01s          
  |++++++++++                                        | 20% ~01s          
  |+++++++++++                                       | 22% ~01s          
  |++++++++++++                                      | 24% ~01s          
  |+++++++++++++                                     | 26% ~00s          
  |++++++++++++++                                    | 28% ~00s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++                                  | 32% ~00s          
  |+++++++++++++++++                                 | 34% ~00s          
  |++++++++++++++++++                                | 36% ~00s          
  |+++++++++++++++++++                               | 38% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++                             | 42% ~00s          
  |++++++++++++++++++++++                            | 44% ~00s          
  |+++++++++++++++++++++++                           | 46% ~00s          
  |++++++++++++++++++++++++                          | 48% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++                        | 52% ~00s          
  |+++++++++++++++++++++++++++                       | 54% ~00s          
  |++++++++++++++++++++++++++++                      | 56% ~00s          
  |+++++++++++++++++++++++++++++                     | 58% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++                   | 62% ~00s          
  |++++++++++++++++++++++++++++++++                  | 64% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~00s          
  |++++++++++++++++++++++++++++++++++                | 68% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~00s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~00s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01s  

  |                                                  | 0 % ~calculating  
  |+                                                 | 2 % ~01s          
  |++                                                | 4 % ~00s          
  |+++                                               | 6 % ~00s          
  |++++                                              | 8 % ~00s          
  |+++++                                             | 10% ~00s          
  |++++++                                            | 12% ~00s          
  |+++++++                                           | 14% ~00s          
  |++++++++                                          | 16% ~00s          
  |+++++++++                                         | 18% ~00s          
  |++++++++++                                        | 20% ~00s          
  |+++++++++++                                       | 22% ~00s          
  |++++++++++++                                      | 24% ~00s          
  |+++++++++++++                                     | 26% ~00s          
  |++++++++++++++                                    | 28% ~00s          
  |+++++++++++++++                                   | 30% ~00s          
  |++++++++++++++++                                  | 32% ~00s          
  |+++++++++++++++++                                 | 34% ~00s          
  |++++++++++++++++++                                | 36% ~00s          
  |+++++++++++++++++++                               | 38% ~00s          
  |++++++++++++++++++++                              | 40% ~00s          
  |+++++++++++++++++++++                             | 42% ~00s          
  |++++++++++++++++++++++                            | 44% ~00s          
  |+++++++++++++++++++++++                           | 46% ~00s          
  |++++++++++++++++++++++++                          | 48% ~00s          
  |+++++++++++++++++++++++++                         | 50% ~00s          
  |++++++++++++++++++++++++++                        | 52% ~00s          
  |+++++++++++++++++++++++++++                       | 54% ~00s          
  |++++++++++++++++++++++++++++                      | 56% ~00s          
  |+++++++++++++++++++++++++++++                     | 58% ~00s          
  |++++++++++++++++++++++++++++++                    | 60% ~00s          
  |+++++++++++++++++++++++++++++++                   | 62% ~00s          
  |++++++++++++++++++++++++++++++++                  | 64% ~00s          
  |+++++++++++++++++++++++++++++++++                 | 66% ~00s          
  |++++++++++++++++++++++++++++++++++                | 68% ~00s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~00s          
  |++++++++++++++++++++++++++++++++++++              | 72% ~00s          
  |+++++++++++++++++++++++++++++++++++++             | 74% ~00s          
  |++++++++++++++++++++++++++++++++++++++            | 76% ~00s          
  |+++++++++++++++++++++++++++++++++++++++           | 78% ~00s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++         | 82% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++        | 84% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++       | 86% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++      | 88% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++    | 92% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++   | 94% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~00s          
  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=00s  
fdr_df_raw = fdr_df
fdr_df = apply(fdr_df, 1:2, \(x) format(x, digits=1)) %>% as.data.frame() #round p values 
fdr_df[fdr_df == 0] = paste0("<",format(.Machine$double.xmin,digits = 1)) # replace p=0 with p<min float
untrace(Seurat:::FindMarkers.default)
Untracing function "FindMarkers.default" in package "Seurat (not-exported)"
# color row name if consistent across patients/models
colors= c()
for (row_num in 1:nrow(logFC_df)) {
  row = logFC_df[row_num,]
  if (sum(row > 0.15)  >= 4) { # if at least x values are more than 0.1 log2FC
    colors <- c(colors, "red")
  }
  else if (sum(row < -0.15)  >= 4) {
    colors <- c(colors, "blue")
  }
  else{colors <- c(colors, "black")}
}
col_fun = circlize::colorRamp2(c(-1, 0, 1), c("blue", "white", "red"))
p = ComplexHeatmap::Heatmap(logFC_df, name = "log2FC on/pre", col = col_fun,
    cell_fun = function(j, i, x, y, width, height, fill) {
        grid.text(fdr_df[i, j], x, y, gp = gpar(fontsize = 8))
}, row_names_gp = gpar(fontsize = 8,col =colors), clustering_method_rows = "average", clustering_distance_rows = "euclidean")
Warning: The input is a data frame, convert it to a matrix.
p
Warning in grSoftVersion() :
  unable to load shared object '/usr/local/lib/R/modules//R_X11.so':
  libXt.so.6: cannot open shared object file: No such file or directory

```r
saveRDS(object = as.grob(p),file = \./Figures/xeno_sipsic_heatmap.rds\)

<!-- rnb-source-end -->


<!-- rnb-output-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->


# Heatmap with asterisks




<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-output-begin eyJkYXRhIjoiXG48IS0tIHJuYi1zb3VyY2UtYmVnaW4gZXlKa1lYUmhJam9pWUdCZ2NseHVJeUJFWlhOamNtbHdkR2x2Ymx4dVptUnlYMlJtWDNOcFp5QTlJR1prY2w5a1psOXlZWGRjYm1aa2NsOWtabDl6YVdkYlhTQThMU0JzWVhCd2JIa29abVJ5WDJSbVgzTnBaeXdnWVhNdWJuVnRaWEpwWXlsY2JseHVZMjl1ZG1WeWRDQThMU0JtZFc1amRHbHZiaWgyWldNcElIdGNiaUFnYzNsdGJuVnRLSFpsWXl3Z1kyOXljaUE5SUVaQlRGTkZMQ0J1WVNBOUlFWkJURk5GTENCamRYUndiMmx1ZEhNZ1BTQmpLREFzSUZ4dUlDQWdJREF1TURBeExDQXdMakF4TENBd0xqQTFMQ0F3TGpFc0lERXBMQ0J6ZVcxaWIyeHpJRDBnWXloY0lpb3FLbHdpTENCY0lpb3FYQ0lzSUZ3aUtsd2lMQ0JjSWk1Y0lpd2dYQ0lnWENJcEtTQWxQaVVnWVhNdVkyaGhjbUZqZEdWeUtDbGNibjBnWEc1Y2JtWmtjbDlrWmw5emFXZGJYU0E5SUdGd2NHeDVLR1prY2w5a1psOXphV2NzSUUxQlVrZEpUaUE5SURFc0lFWlZUaUE5SUdOdmJuWmxjblFwWEc1Z1lHQWlmUT09IC0tPlxuXG5gYGByXG4jIERlc2NyaXB0aW9uXG5mZHJfZGZfc2lnID0gZmRyX2RmX3Jhd1xuZmRyX2RmX3NpZ1tdIDwtIGxhcHBseShmZHJfZGZfc2lnLCBhcy5udW1lcmljKVxuXG5jb252ZXJ0IDwtIGZ1bmN0aW9uKHZlYykge1xuICBzeW1udW0odmVjLCBjb3JyID0gRkFMU0UsIG5hID0gRkFMU0UsIGN1dHBvaW50cyA9IGMoMCwgXG4gICAgMC4wMDEsIDAuMDEsIDAuMDUsIDAuMSwgMSksIHN5bWJvbHMgPSBjKFwiKioqXCIsIFwiKipcIiwgXCIqXCIsIFwiLlwiLCBcIiBcIikpICU+JSBhcy5jaGFyYWN0ZXIoKVxufSBcblxuZmRyX2RmX3NpZ1tdID0gYXBwbHkoZmRyX2RmX3NpZywgTUFSR0lOID0gMSwgRlVOID0gY29udmVydClcbmBgYFxuXG48IS0tIHJuYi1zb3VyY2UtZW5kIC0tPlxuIn0= -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuIyBEZXNjcmlwdGlvblxuZmRyX2RmX3NpZyA9IGZkcl9kZl9yYXdcbmZkcl9kZl9zaWdbXSA8LSBsYXBwbHkoZmRyX2RmX3NpZywgYXMubnVtZXJpYylcblxuY29udmVydCA8LSBmdW5jdGlvbih2ZWMpIHtcbiAgc3ltbnVtKHZlYywgY29yciA9IEZBTFNFLCBuYSA9IEZBTFNFLCBjdXRwb2ludHMgPSBjKDAsIFxuICAgIDAuMDAxLCAwLjAxLCAwLjA1LCAwLjEsIDEpLCBzeW1ib2xzID0gYyhcIioqKlwiLCBcIioqXCIsIFwiKlwiLCBcIi5cIiwgXCIgXCIpKSAlPiUgYXMuY2hhcmFjdGVyKClcbn0gXG5cbmZkcl9kZl9zaWdbXSA9IGFwcGx5KGZkcl9kZl9zaWcsIE1BUkdJTiA9IDEsIEZVTiA9IGNvbnZlcnQpXG5gYGAifQ== -->

```r
# Description
fdr_df_sig = fdr_df_raw
fdr_df_sig[] <- lapply(fdr_df_sig, as.numeric)

convert <- function(vec) {
  symnum(vec, corr = FALSE, na = FALSE, cutpoints = c(0, 
    0.001, 0.01, 0.05, 0.1, 1), symbols = c("***", "**", "*", ".", " ")) %>% as.character()
} 

fdr_df_sig[] = apply(fdr_df_sig, MARGIN = 1, FUN = convert)
col_fun = circlize::colorRamp2(c(-1, 0, 1), c("blue", "white", "red"))
p = ComplexHeatmap::Heatmap(logFC_df, name = "log2FC on/pre", col = col_fun,
    cell_fun = function(j, i, x, y, width, height, fill) {
        grid.text(fdr_df_sig[i, j], x, y, gp = gpar(fontsize = 8))
}, row_names_gp = gpar(fontsize = 8,col =colors), clustering_method_rows = "average", clustering_distance_rows = "euclidean")
Warning: The input is a data frame, convert it to a matrix.
p

4 Heatmap

DefaultAssay(xeno) = "sipsic"
data = FetchData(object = xeno, vars = c(pathways_names,"orig.ident"))
data[] <- data %>%  group_by(orig.ident) %>% mutate(across(is.numeric, ~ as.numeric(scale(.)))) %>% ungroup() 
data = data %>% select(-orig.ident) 
data = data %>% t() %>% as.data.frame()

annotation_data = FetchData(object = xeno, vars = c("orig.ident","treatment")) %>% dplyr::arrange(orig.ident,treatment)
column_ha = HeatmapAnnotation(df = annotation_data[,2])
data = data[,rownames(annotation_data)] #order data like annotation
data = na.omit(data)
p = ComplexHeatmap::Heatmap(
  data,
  show_column_names = F,
  row_names_gp = grid::gpar(fontsize = 7),
  cluster_rows = T,
  top_annotation = column_ha,
  name = "Z-score expression",use_raster = F,cluster_columns = F,column_split   = annotation_data$orig.ident,
  column_gap = unit(2, "mm"), border = TRUE,show_parent_dend_line = FALSE, show_column_dend = FALSE,cluster_column_slices = F
)
Warning: The input is a data frame, convert it to a matrix.
The automatically generated colors map from the minus and plus 99^th of the absolute values in the
matrix. There are outliers in the matrix whose patterns might be hidden by this color mapping. You can
manually set the color to `col` argument.

Use `suppressMessages()` to turn off this message.
  
p

# heatmap with clutering per model and time point
DefaultAssay(xeno) = "sipsic"
data = FetchData(object = xeno, vars = c(pathways_names,"orig.ident"))
data[] <- data %>%  group_by(orig.ident) %>%
  mutate(across(is.numeric, ~ as.numeric(scale(.)))) %>% ungroup() # scale per model
Warning: Problem while computing `..1 = across(is.numeric, ~as.numeric(scale(.)))`.
ℹ Predicate functions must be wrapped in `where()`.

# Bad data %>% select(is.numeric)

# Good data %>% select(where(is.numeric))

ℹ Please update your code. This message is displayed once per session.
ℹ The warning occurred in group 0: character(0).
data = data %>% select(-orig.ident) # remove ident var
data = data %>% t() %>% as.data.frame()

annotation_data = FetchData(object = xeno, vars = c("orig.ident","treatment")) %>% dplyr::arrange(orig.ident,treatment)
column_ha = HeatmapAnnotation(Treatment = annotation_data[,2], #set annotation
                              col = list(Treatment = c("NT" = "red", "OSI" = "green", "res" = "blue"))) 
data = data[,rownames(annotation_data)] #order data like annotation
data = na.omit(data)
column_split = paste(annotation_data$orig.ident,annotation_data$treatment,sep = "\n") #split by ident+tp
column_names = unique(column_split) %>% gsub(pattern = "119\nOSI",replacement = "      119\n      OSI") #adujst location to avoid overlap
DefaultAssay(xeno) = "RNA" #make RNA default again

p = ComplexHeatmap::Heatmap(
  data,
  show_column_names = F,
  row_names_gp = grid::gpar(fontsize = 10),
  cluster_rows = T,
  top_annotation = column_ha,
  name = "Z-score expression",use_raster = F,cluster_columns = T,column_split = column_split,
  column_title = column_names,
  column_gap = unit(2, "mm"), border = TRUE,show_parent_dend_line = FALSE, show_column_dend = F,cluster_column_slices = F)
Warning: The input is a data frame, convert it to a matrix.
The automatically generated colors map from the minus and plus 99^th of the absolute values in the matrix. There are outliers
in the matrix whose patterns might be hidden by this color mapping. You can manually set the color to `col` argument.

Use `suppressMessages()` to turn off this message.
  
p

# only nmf programs
for (patient_name in unique(xeno$orig.ident)) {
  
  patient_data = subset(xeno,subset = orig.ident == patient_name)
  pathways_names = c("HALLMARK-INTERFERON-ALPHA-RESPONSE","HALLMARK-TNFA-SIGNALING-VIA-NFKB", "HALLMARK-HYPOXIA","HALLMARK-E2F-TARGETS" )
  
  DefaultAssay(patient_data) = "sipsic"
  data = FetchData(object = patient_data, vars = c(pathways_names))
  data[] <- data %>% 
    mutate(across(everything(), ~ as.numeric(scale(.))))  # scale per pathway
  data = data %>% t() %>% as.data.frame()
  
  annotation_data = FetchData(object = patient_data, vars = c("treatment")) %>% dplyr::arrange(treatment)
  column_ha = HeatmapAnnotation(Treatment = annotation_data[,1], #set annotation
                                col = list(Treatment = c("NT" = "red", "OSI" = "green", "res" = "blue"))) 
  data = data[,rownames(annotation_data)] #order data like annotation
  data = na.omit(data)
  DefaultAssay(xeno) = "RNA" #make RNA default again
  
  p = ComplexHeatmap::Heatmap(
    data,
    show_column_names = F,
    row_names_gp = grid::gpar(fontsize = 10),
    cluster_rows = T,
    top_annotation = column_ha,
    name = "Z-score expression",use_raster = F,cluster_columns = T,column_split = annotation_data$treatment,
    column_gap = unit(2, "mm"), border = TRUE,show_parent_dend_line = FALSE, show_column_dend = T,cluster_column_slices = F,column_title = patient_name)
  
    
  print(p)
}
Warning: The input is a data frame, convert it to a matrix.
Warning in grSoftVersion() :
  unable to load shared object '/usr/local/lib/R/modules//R_X11.so':
  libXt.so.6: cannot open shared object file: No such file or directory
Warning: The input is a data frame, convert it to a matrix.
The automatically generated colors map from the minus and plus 99^th of the absolute values in the matrix. There are outliers
in the matrix whose patterns might be hidden by this color mapping. You can manually set the color to `col` argument.

Use `suppressMessages()` to turn off this message.
Warning: The input is a data frame, convert it to a matrix.
The automatically generated colors map from the minus and plus 99^th of the absolute values in the matrix. There are outliers
in the matrix whose patterns might be hidden by this color mapping. You can manually set the color to `col` argument.

Use `suppressMessages()` to turn off this message.
Warning: The input is a data frame, convert it to a matrix.
Warning: The input is a data frame, convert it to a matrix.
The automatically generated colors map from the minus and plus 99^th of the absolute values in the matrix. There are outliers
in the matrix whose patterns might be hidden by this color mapping. You can manually set the color to `col` argument.

Use `suppressMessages()` to turn off this message.
Warning: The input is a data frame, convert it to a matrix.
The automatically generated colors map from the minus and plus 99^th of the absolute values in the matrix. There are outliers
in the matrix whose patterns might be hidden by this color mapping. You can manually set the color to `col` argument.

Use `suppressMessages()` to turn off this message.

5 Correlation

# Description
for (patient_name in unique(xeno$orig.ident)) {
  
  patient_data = subset(xeno, subset = orig.ident == patient_name)
  pathways_names = c(
    "HALLMARK-INTERFERON-ALPHA-RESPONSE",
    "HALLMARK-TNFA-SIGNALING-VIA-NFKB",
    "HALLMARK-HYPOXIA",
    "HALLMARK-E2F-TARGETS"
  )
  
  DefaultAssay(patient_data) = "sipsic"
  data = FetchData(object = patient_data, vars = c(pathways_names))
  data[] <- data %>%
    mutate(across(everything(), ~ as.numeric(scale(.))))  # scale per pathway
  
  
  data = na.omit(data)
  DefaultAssay(xeno) = "RNA" #make RNA default again
  colnames(data) = c("H_INFa", "H_TNFa_NFKb", "H_HYPOXIA", "H_E2F")
  library(circlize)
  data = cor(data)
  col_fun = colorRamp2(c(-1, 0, 1), c("blue", "white", "red"))
 p =  Heatmap(
    data, name = "pearson", col = col_fun, show_row_names = F, column_title = patient_name,
    cell_fun = function(j, i, x, y, width, height, fill) {
      grid.text(as.character(round(data[i, j], digits = 2)), x, y, gp = gpar(fontsize = 10))
    }
  )
 print(p)
}

6 Ternary plot

p_list
$`119`

$PC9

$`1109`

$`1071`

$`1157`

$`1068`

p_list
$`119`
Warning: Removed 263 rows containing missing values (geom_point).

$PC9
Warning: Removed 4629 rows containing missing values (geom_point).

$`1109`
Warning: Removed 2574 rows containing missing values (geom_point).

$`1071`
Warning: Removed 2918 rows containing missing values (geom_point).

$`1157`
Error in `f()`:
! Insufficient values in manual scale. 3 needed but only 2 provided.
Backtrace:
  1. base `<fn>`(x)
  2. ggtern:::print.ggplot(x)
  4. ggtern:::ggplot_build.ggplot(x)
  5. base::lapply(data, ggint$scales_map_df, scales = npscales)
  6. ggplot2 FUN(X[[i]], ...)
     ...
 13. ggplot2 FUN(X[[i]], ...)
 14. self$map(df[[j]])
 15. ggplot2 f(..., self = self)
 16. self$palette(n)
 17. ggplot2 f(...)

 ggtern(data=df,ggtern::aes(x,y,z)) + geom_point()+
  theme_tropical(base_size=14)
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"
[1] "not scaling"

# plot
do.call(ggtern::grid.arrange,args = c(p_list,ncol=3))

LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Ci5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiA4NSUgIWltcG9ydGFudDsKICBtYXJnaW46IGF1dG87Cn0KPC9zdHlsZT4KCgojIEZ1bmN0aW9ucwoKYGBge3J9CmxpYnJhcnkoc3RyaW5naSkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KGdncGxvdGlmeSkKCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAiREVHX2Z1bmN0aW9ucyIsdmVyc2lvbiA9ICIwLjIuNDciKQpzb3VyY2VfZnJvbV9naXRodWIocmVwb3NpdG95ID0gImNOTUZfZnVuY3Rpb25zIix2ZXJzaW9uID0gIjAuNC4wNCIsc2NyaXB0X25hbWUgPSAiY25tZl9mdW5jdGlvbnNfVjMuUiIpCnNvdXJjZV9mcm9tX2dpdGh1YihyZXBvc2l0b3kgPSAic2NfZ2VuZXJhbF9mdW5jdGlvbnMiLHZlcnNpb24gPSAiMC4xLjM0IixzY3JpcHRfbmFtZSA9ICJmdW5jdGlvbnMuUiIpCgoKYGBgCgojIERhdGEKCgpgYGB7cn0KeGVubyA8LSBxczo6cXJlYWQoIi4vcmF3X2RhdGEveGVuby5xcyIpCmBgYAoKCiMgREUgcGF0aHdheXMKCgpgYGB7cn0KcGF0aHdheVNjb3Jlc01hdHJpeCA9IHJlYWRfcmRzKGZpbGUgPSAiLi9vdXRwdXRfZGF0YS9ydW5fU2lQU2lDL3BhdGh3YXlTY29yZXNNYXRyaXguUkRTIikKeGVub1tbInNpcHNpYyJdXSA9IENyZWF0ZUFzc2F5T2JqZWN0KGNvdW50cyA9IHBhdGh3YXlTY29yZXNNYXRyaXgpCgpgYGAKCmBgYHtyfQp0cmFjZShTZXVyYXQ6OjpGaW5kTWFya2Vycy5kZWZhdWx0LGVkaXQgPSBUKSAjcmVwbGFjZSAiYm9uZmVycm9uaSIgd2l0aCAiZmRyIgoKYGBgCgpgYGB7cn0KeGVubyA9IFNldElkZW50KHhlbm8sIHZhbHVlID0gInRyZWF0bWVudCIpCnBhdGh3YXlzX25hbWVzID0gZ3N1Yihyb3duYW1lcyhwYXRod2F5U2NvcmVzTWF0cml4KSwgcGF0dGVybiA9ICJfIiwgcmVwbGFjZW1lbnQgPSAiLSIpCgoKbG9nRkNfZGYgPSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHBhdGh3YXlzX25hbWVzKQpmZHJfZGYgPSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IHBhdGh3YXlzX25hbWVzKQoKZm9yIChtb2RlbCBpbiB1bmlxdWUoeGVubyRvcmlnLmlkZW50KSkgewogIG1vZGVsX2RhdGEgPSBzdWJzZXQoeGVubywgc3Vic2V0ID0gb3JpZy5pZGVudCA9PSBtb2RlbCkKICBwYXRod2F5X21hcmtlcnMgPSBGaW5kTWFya2VycygKICAgIG9iamVjdCA9IG1vZGVsX2RhdGEsCiAgICBpZGVudC4xID0gIk9TSSIsCiAgICBpZGVudC4yID0gIk5UIiwKICAgIGFzc2F5ID0gInNpcHNpYyIsCiAgICBzbG90ID0gImNvdW50cyIsCiAgICBsb2dmYy50aHJlc2hvbGQgPSAwLAogICAgZGVuc2lmeSA9IFQsCiAgICBwc2V1ZG9jb3VudC51c2UgPSAwLjAwMSwKICAgIGZlYXR1cmVzID0gcGF0aHdheXNfbmFtZXMKICApCiAgYXZnX2xvZzJGQyA9IHBhdGh3YXlfbWFya2Vyc1twYXRod2F5c19uYW1lcywgImF2Z19sb2cyRkMiLCBkcm9wID0gRl0KICBjb2xuYW1lcyhhdmdfbG9nMkZDKSA9IG1vZGVsCiAgcGF0aHdheV9tYXJrZXJzICAlPD4lICBkcGx5cjo6cmVuYW1lKGZkciA9IHBfdmFsX2FkaikKICBmZHIgPSBwYXRod2F5X21hcmtlcnNbcGF0aHdheXNfbmFtZXMsICJmZHIiLCBkcm9wID0gRl0KICBjb2xuYW1lcyhmZHIpID0gbW9kZWwKICAKICBsb2dGQ19kZiA9IGNiaW5kKGxvZ0ZDX2RmLCBhdmdfbG9nMkZDKQogIGZkcl9kZiA9IGNiaW5kKGZkcl9kZiwgZmRyKQp9CmZkcl9kZl9yYXcgPSBmZHJfZGYKZmRyX2RmID0gYXBwbHkoZmRyX2RmLCAxOjIsIFwoeCkgZm9ybWF0KHgsIGRpZ2l0cz0xKSkgJT4lIGFzLmRhdGEuZnJhbWUoKSAjcm91bmQgcCB2YWx1ZXMgCmZkcl9kZltmZHJfZGYgPT0gMF0gPSBwYXN0ZTAoIjwiLGZvcm1hdCguTWFjaGluZSRkb3VibGUueG1pbixkaWdpdHMgPSAxKSkgIyByZXBsYWNlIHA9MCB3aXRoIHA8bWluIGZsb2F0CmBgYApgYGB7cn0KdW50cmFjZShTZXVyYXQ6OjpGaW5kTWFya2Vycy5kZWZhdWx0KQoKYGBgCgoKCmBgYHtyfQojIGNvbG9yIHJvdyBuYW1lIGlmIGNvbnNpc3RlbnQgYWNyb3NzIHBhdGllbnRzL21vZGVscwpjb2xvcnM9IGMoKQpmb3IgKHJvd19udW0gaW4gMTpucm93KGxvZ0ZDX2RmKSkgewogIHJvdyA9IGxvZ0ZDX2RmW3Jvd19udW0sXQogIGlmIChzdW0ocm93ID4gMC4xNSkgID49IDQpIHsgIyBpZiBhdCBsZWFzdCB4IHZhbHVlcyBhcmUgbW9yZSB0aGFuIDAuMSBsb2cyRkMKICAgIGNvbG9ycyA8LSBjKGNvbG9ycywgInJlZCIpCiAgfQogIGVsc2UgaWYgKHN1bShyb3cgPCAtMC4xNSkgID49IDQpIHsKICAgIGNvbG9ycyA8LSBjKGNvbG9ycywgImJsdWUiKQogIH0KICBlbHNle2NvbG9ycyA8LSBjKGNvbG9ycywgImJsYWNrIil9Cn0KCmBgYAoKYGBge3IgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OH0KY29sX2Z1biA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMoLTEsIDAsIDEpLCBjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKQpwID0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAobG9nRkNfZGYsIG5hbWUgPSAibG9nMkZDIG9uL3ByZSIsIGNvbCA9IGNvbF9mdW4sCiAgICBjZWxsX2Z1biA9IGZ1bmN0aW9uKGosIGksIHgsIHksIHdpZHRoLCBoZWlnaHQsIGZpbGwpIHsKICAgICAgICBncmlkLnRleHQoZmRyX2RmW2ksIGpdLCB4LCB5LCBncCA9IGdwYXIoZm9udHNpemUgPSA4KSkKfSwgcm93X25hbWVzX2dwID0gZ3Bhcihmb250c2l6ZSA9IDgsY29sID1jb2xvcnMpLCBjbHVzdGVyaW5nX21ldGhvZF9yb3dzID0gImF2ZXJhZ2UiLCBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3MgPSAiZXVjbGlkZWFuIikKcApgYGAKCmBgYHtyfQpzYXZlUkRTKG9iamVjdCA9IGFzLmdyb2IocCksZmlsZSA9ICIuL0ZpZ3VyZXMveGVub19zaXBzaWNfaGVhdG1hcC5yZHMiKQpgYGAKCiMgSGVhdG1hcCB3aXRoIGFzdGVyaXNrcwoKCgpgYGB7cn0KIyBEZXNjcmlwdGlvbgpmZHJfZGZfc2lnID0gZmRyX2RmX3JhdwpmZHJfZGZfc2lnW10gPC0gbGFwcGx5KGZkcl9kZl9zaWcsIGFzLm51bWVyaWMpCgpjb252ZXJ0IDwtIGZ1bmN0aW9uKHZlYykgewogIHN5bW51bSh2ZWMsIGNvcnIgPSBGQUxTRSwgbmEgPSBGQUxTRSwgY3V0cG9pbnRzID0gYygwLCAKICAgIDAuMDAxLCAwLjAxLCAwLjA1LCAwLjEsIDEpLCBzeW1ib2xzID0gYygiKioqIiwgIioqIiwgIioiLCAiLiIsICIgIikpICU+JSBhcy5jaGFyYWN0ZXIoKQp9IAoKZmRyX2RmX3NpZ1tdID0gYXBwbHkoZmRyX2RmX3NpZywgTUFSR0lOID0gMSwgRlVOID0gY29udmVydCkKYGBgCgoKYGBge3IgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OH0KY29sX2Z1biA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMoLTEsIDAsIDEpLCBjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKQpwID0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAobG9nRkNfZGYsIG5hbWUgPSAibG9nMkZDIG9uL3ByZSIsIGNvbCA9IGNvbF9mdW4sCiAgICBjZWxsX2Z1biA9IGZ1bmN0aW9uKGosIGksIHgsIHksIHdpZHRoLCBoZWlnaHQsIGZpbGwpIHsKICAgICAgICBncmlkLnRleHQoZmRyX2RmX3NpZ1tpLCBqXSwgeCwgeSwgZ3AgPSBncGFyKGZvbnRzaXplID0gOCkpCn0sIHJvd19uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSA4LGNvbCA9Y29sb3JzKSwgY2x1c3RlcmluZ19tZXRob2Rfcm93cyA9ICJhdmVyYWdlIiwgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gImV1Y2xpZGVhbiIpCnAKYGBgCgojIEhlYXRtYXAKYGBge3IgZmlnLmhlaWdodD0xNX0KRGVmYXVsdEFzc2F5KHhlbm8pID0gInNpcHNpYyIKZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSB4ZW5vLCB2YXJzID0gYyhwYXRod2F5c19uYW1lcywib3JpZy5pZGVudCIpKQpkYXRhW10gPC0gZGF0YSAlPiUgIGdyb3VwX2J5KG9yaWcuaWRlbnQpICU+JSBtdXRhdGUoYWNyb3NzKGlzLm51bWVyaWMsIH4gYXMubnVtZXJpYyhzY2FsZSguKSkpKSAlPiUgdW5ncm91cCgpIApkYXRhID0gZGF0YSAlPiUgc2VsZWN0KC1vcmlnLmlkZW50KSAKZGF0YSA9IGRhdGEgJT4lIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpCgphbm5vdGF0aW9uX2RhdGEgPSBGZXRjaERhdGEob2JqZWN0ID0geGVubywgdmFycyA9IGMoIm9yaWcuaWRlbnQiLCJ0cmVhdG1lbnQiKSkgJT4lIGRwbHlyOjphcnJhbmdlKG9yaWcuaWRlbnQsdHJlYXRtZW50KQpjb2x1bW5faGEgPSBIZWF0bWFwQW5ub3RhdGlvbihkZiA9IGFubm90YXRpb25fZGF0YVssMl0pCmRhdGEgPSBkYXRhWyxyb3duYW1lcyhhbm5vdGF0aW9uX2RhdGEpXSAjb3JkZXIgZGF0YSBsaWtlIGFubm90YXRpb24KZGF0YSA9IG5hLm9taXQoZGF0YSkKcCA9IENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKAogIGRhdGEsCiAgc2hvd19jb2x1bW5fbmFtZXMgPSBGLAogIHJvd19uYW1lc19ncCA9IGdyaWQ6OmdwYXIoZm9udHNpemUgPSA3KSwKICBjbHVzdGVyX3Jvd3MgPSBULAogIHRvcF9hbm5vdGF0aW9uID0gY29sdW1uX2hhLAogIG5hbWUgPSAiWi1zY29yZSBleHByZXNzaW9uIix1c2VfcmFzdGVyID0gRixjbHVzdGVyX2NvbHVtbnMgPSBGLGNvbHVtbl9zcGxpdCAgID0gYW5ub3RhdGlvbl9kYXRhJG9yaWcuaWRlbnQsCiAgY29sdW1uX2dhcCA9IHVuaXQoMiwgIm1tIiksIGJvcmRlciA9IFRSVUUsc2hvd19wYXJlbnRfZGVuZF9saW5lID0gRkFMU0UsIHNob3dfY29sdW1uX2RlbmQgPSBGQUxTRSxjbHVzdGVyX2NvbHVtbl9zbGljZXMgPSBGCikKICAKcApgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTV9CiMgaGVhdG1hcCB3aXRoIGNsdXRlcmluZyBwZXIgbW9kZWwgYW5kIHRpbWUgcG9pbnQKRGVmYXVsdEFzc2F5KHhlbm8pID0gInNpcHNpYyIKZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSB4ZW5vLCB2YXJzID0gYyhwYXRod2F5c19uYW1lcywib3JpZy5pZGVudCIpKQpkYXRhW10gPC0gZGF0YSAlPiUgIGdyb3VwX2J5KG9yaWcuaWRlbnQpICU+JQogIG11dGF0ZShhY3Jvc3MoaXMubnVtZXJpYywgfiBhcy5udW1lcmljKHNjYWxlKC4pKSkpICU+JSB1bmdyb3VwKCkgIyBzY2FsZSBwZXIgbW9kZWwKZGF0YSA9IGRhdGEgJT4lIHNlbGVjdCgtb3JpZy5pZGVudCkgIyByZW1vdmUgaWRlbnQgdmFyCmRhdGEgPSBkYXRhICU+JSB0KCkgJT4lIGFzLmRhdGEuZnJhbWUoKQoKYW5ub3RhdGlvbl9kYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IHhlbm8sIHZhcnMgPSBjKCJvcmlnLmlkZW50IiwidHJlYXRtZW50IikpICU+JSBkcGx5cjo6YXJyYW5nZShvcmlnLmlkZW50LHRyZWF0bWVudCkKY29sdW1uX2hhID0gSGVhdG1hcEFubm90YXRpb24oVHJlYXRtZW50ID0gYW5ub3RhdGlvbl9kYXRhWywyXSwgI3NldCBhbm5vdGF0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGxpc3QoVHJlYXRtZW50ID0gYygiTlQiID0gInJlZCIsICJPU0kiID0gImdyZWVuIiwgInJlcyIgPSAiYmx1ZSIpKSkgCmRhdGEgPSBkYXRhWyxyb3duYW1lcyhhbm5vdGF0aW9uX2RhdGEpXSAjb3JkZXIgZGF0YSBsaWtlIGFubm90YXRpb24KZGF0YSA9IG5hLm9taXQoZGF0YSkKY29sdW1uX3NwbGl0ID0gcGFzdGUoYW5ub3RhdGlvbl9kYXRhJG9yaWcuaWRlbnQsYW5ub3RhdGlvbl9kYXRhJHRyZWF0bWVudCxzZXAgPSAiXG4iKSAjc3BsaXQgYnkgaWRlbnQrdHAKY29sdW1uX25hbWVzID0gdW5pcXVlKGNvbHVtbl9zcGxpdCkgJT4lIGdzdWIocGF0dGVybiA9ICIxMTlcbk9TSSIscmVwbGFjZW1lbnQgPSAiICAgICAgMTE5XG4gICAgICBPU0kiKSAjYWR1anN0IGxvY2F0aW9uIHRvIGF2b2lkIG92ZXJsYXAKRGVmYXVsdEFzc2F5KHhlbm8pID0gIlJOQSIgI21ha2UgUk5BIGRlZmF1bHQgYWdhaW4KCnAgPSBDb21wbGV4SGVhdG1hcDo6SGVhdG1hcCgKICBkYXRhLAogIHNob3dfY29sdW1uX25hbWVzID0gRiwKICByb3dfbmFtZXNfZ3AgPSBncmlkOjpncGFyKGZvbnRzaXplID0gMTApLAogIGNsdXN0ZXJfcm93cyA9IFQsCiAgdG9wX2Fubm90YXRpb24gPSBjb2x1bW5faGEsCiAgbmFtZSA9ICJaLXNjb3JlIGV4cHJlc3Npb24iLHVzZV9yYXN0ZXIgPSBGLGNsdXN0ZXJfY29sdW1ucyA9IFQsY29sdW1uX3NwbGl0ID0gY29sdW1uX3NwbGl0LAogIGNvbHVtbl90aXRsZSA9IGNvbHVtbl9uYW1lcywKICBjb2x1bW5fZ2FwID0gdW5pdCgyLCAibW0iKSwgYm9yZGVyID0gVFJVRSxzaG93X3BhcmVudF9kZW5kX2xpbmUgPSBGQUxTRSwgc2hvd19jb2x1bW5fZGVuZCA9IEYsY2x1c3Rlcl9jb2x1bW5fc2xpY2VzID0gRikKCiAgCnAKYGBgCgpgYGB7ciBmaWcud2lkdGg9MTB9CiMgb25seSBubWYgcHJvZ3JhbXMKZm9yIChwYXRpZW50X25hbWUgaW4gdW5pcXVlKHhlbm8kb3JpZy5pZGVudCkpIHsKICAKICBwYXRpZW50X2RhdGEgPSBzdWJzZXQoeGVubyxzdWJzZXQgPSBvcmlnLmlkZW50ID09IHBhdGllbnRfbmFtZSkKICBwYXRod2F5c19uYW1lcyA9IGMoIkhBTExNQVJLLUlOVEVSRkVST04tQUxQSEEtUkVTUE9OU0UiLCJIQUxMTUFSSy1UTkZBLVNJR05BTElORy1WSUEtTkZLQiIsICJIQUxMTUFSSy1IWVBPWElBIiwiSEFMTE1BUkstRTJGLVRBUkdFVFMiICkKICAKICBEZWZhdWx0QXNzYXkocGF0aWVudF9kYXRhKSA9ICJzaXBzaWMiCiAgZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBwYXRpZW50X2RhdGEsIHZhcnMgPSBjKHBhdGh3YXlzX25hbWVzKSkKICBkYXRhW10gPC0gZGF0YSAlPiUgCiAgICBtdXRhdGUoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfiBhcy5udW1lcmljKHNjYWxlKC4pKSkpICAjIHNjYWxlIHBlciBwYXRod2F5CiAgZGF0YSA9IGRhdGEgJT4lIHQoKSAlPiUgYXMuZGF0YS5mcmFtZSgpCiAgCiAgYW5ub3RhdGlvbl9kYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IHBhdGllbnRfZGF0YSwgdmFycyA9IGMoInRyZWF0bWVudCIpKSAlPiUgZHBseXI6OmFycmFuZ2UodHJlYXRtZW50KQogIGNvbHVtbl9oYSA9IEhlYXRtYXBBbm5vdGF0aW9uKFRyZWF0bWVudCA9IGFubm90YXRpb25fZGF0YVssMV0sICNzZXQgYW5ub3RhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbCA9IGxpc3QoVHJlYXRtZW50ID0gYygiTlQiID0gInJlZCIsICJPU0kiID0gImdyZWVuIiwgInJlcyIgPSAiYmx1ZSIpKSkgCiAgZGF0YSA9IGRhdGFbLHJvd25hbWVzKGFubm90YXRpb25fZGF0YSldICNvcmRlciBkYXRhIGxpa2UgYW5ub3RhdGlvbgogIGRhdGEgPSBuYS5vbWl0KGRhdGEpCiAgRGVmYXVsdEFzc2F5KHhlbm8pID0gIlJOQSIgI21ha2UgUk5BIGRlZmF1bHQgYWdhaW4KICAKICBwID0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoCiAgICBkYXRhLAogICAgc2hvd19jb2x1bW5fbmFtZXMgPSBGLAogICAgcm93X25hbWVzX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIGNsdXN0ZXJfcm93cyA9IFQsCiAgICB0b3BfYW5ub3RhdGlvbiA9IGNvbHVtbl9oYSwKICAgIG5hbWUgPSAiWi1zY29yZSBleHByZXNzaW9uIix1c2VfcmFzdGVyID0gRixjbHVzdGVyX2NvbHVtbnMgPSBULGNvbHVtbl9zcGxpdCA9IGFubm90YXRpb25fZGF0YSR0cmVhdG1lbnQsCiAgICBjb2x1bW5fZ2FwID0gdW5pdCgyLCAibW0iKSwgYm9yZGVyID0gVFJVRSxzaG93X3BhcmVudF9kZW5kX2xpbmUgPSBGQUxTRSwgc2hvd19jb2x1bW5fZGVuZCA9IFQsY2x1c3Rlcl9jb2x1bW5fc2xpY2VzID0gRixjb2x1bW5fdGl0bGUgPSBwYXRpZW50X25hbWUpCiAgCiAgICAKICBwcmludChwKQp9CmBgYAoKCiMgQ29ycmVsYXRpb24KCmBgYHtyfQojIERlc2NyaXB0aW9uCmZvciAocGF0aWVudF9uYW1lIGluIHVuaXF1ZSh4ZW5vJG9yaWcuaWRlbnQpKSB7CiAgCiAgcGF0aWVudF9kYXRhID0gc3Vic2V0KHhlbm8sIHN1YnNldCA9IG9yaWcuaWRlbnQgPT0gcGF0aWVudF9uYW1lKQogIHBhdGh3YXlzX25hbWVzID0gYygKICAgICJIQUxMTUFSSy1JTlRFUkZFUk9OLUFMUEhBLVJFU1BPTlNFIiwKICAgICJIQUxMTUFSSy1UTkZBLVNJR05BTElORy1WSUEtTkZLQiIsCiAgICAiSEFMTE1BUkstSFlQT1hJQSIsCiAgICAiSEFMTE1BUkstRTJGLVRBUkdFVFMiCiAgKQogIAogIERlZmF1bHRBc3NheShwYXRpZW50X2RhdGEpID0gInNpcHNpYyIKICBkYXRhID0gRmV0Y2hEYXRhKG9iamVjdCA9IHBhdGllbnRfZGF0YSwgdmFycyA9IGMocGF0aHdheXNfbmFtZXMpKQogIGRhdGFbXSA8LSBkYXRhICU+JQogICAgbXV0YXRlKGFjcm9zcyhldmVyeXRoaW5nKCksIH4gYXMubnVtZXJpYyhzY2FsZSguKSkpKSAgIyBzY2FsZSBwZXIgcGF0aHdheQogIAogIAogIGRhdGEgPSBuYS5vbWl0KGRhdGEpCiAgRGVmYXVsdEFzc2F5KHhlbm8pID0gIlJOQSIgI21ha2UgUk5BIGRlZmF1bHQgYWdhaW4KICBjb2xuYW1lcyhkYXRhKSA9IGMoIkhfSU5GYSIsICJIX1RORmFfTkZLYiIsICJIX0hZUE9YSUEiLCAiSF9FMkYiKQogIGxpYnJhcnkoY2lyY2xpemUpCiAgZGF0YSA9IGNvcihkYXRhKQogIGNvbF9mdW4gPSBjb2xvclJhbXAyKGMoLTEsIDAsIDEpLCBjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKQogcCA9ICBIZWF0bWFwKAogICAgZGF0YSwgbmFtZSA9ICJwZWFyc29uIiwgY29sID0gY29sX2Z1biwgc2hvd19yb3dfbmFtZXMgPSBGLCBjb2x1bW5fdGl0bGUgPSBwYXRpZW50X25hbWUsCiAgICBjZWxsX2Z1biA9IGZ1bmN0aW9uKGosIGksIHgsIHksIHdpZHRoLCBoZWlnaHQsIGZpbGwpIHsKICAgICAgZ3JpZC50ZXh0KGFzLmNoYXJhY3Rlcihyb3VuZChkYXRhW2ksIGpdLCBkaWdpdHMgPSAyKSksIHgsIHksIGdwID0gZ3Bhcihmb250c2l6ZSA9IDEwKSkKICAgIH0KICApCiBwcmludChwKQp9CmBgYAoKCiMgVGVybmFyeSBwbG90CgpgYGB7cn0KIyBEZXNjcmlwdGlvbgpsaWJyYXJ5KGdndGVybikKcF9saXN0ID0gbGlzdCgpCgpmb3IgKHBhdGllbnRfbmFtZSBpbiB1bmlxdWUoeGVubyRvcmlnLmlkZW50KSkgewogIHBhdGllbnRfZGF0YSA9IHN1YnNldCh4ZW5vLHN1YnNldCA9IG9yaWcuaWRlbnQgPT0gcGF0aWVudF9uYW1lKQogIHBhdGh3YXlzX25hbWVzID0gYygKICAgICJIQUxMTUFSSy1JTlRFUkZFUk9OLUFMUEhBLVJFU1BPTlNFIiwKICAgICJIQUxMTUFSSy1UTkZBLVNJR05BTElORy1WSUEtTkZLQiIsCiAgICAiSEFMTE1BUkstSFlQT1hJQSIKICApCiAgCiAgRGVmYXVsdEFzc2F5KHBhdGllbnRfZGF0YSkgPSAic2lwc2ljIgogIGRhdGEgPSBGZXRjaERhdGEob2JqZWN0ID0gcGF0aWVudF9kYXRhLCB2YXJzID0gYyhwYXRod2F5c19uYW1lcykpCiAgZGF0YVtdIDwtIGRhdGEgJT4lCiAgICBtdXRhdGUoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfiBhcy5udW1lcmljKG1pbl9tYXhfbm9ybWFsaXplKC4pKSkpICAjIHNjYWxlIHBlciBwYXRod2F5CiAgZGF0YSA9IGRhdGFbY29sbmFtZXMocGF0aWVudF9kYXRhKVtwYXRpZW50X2RhdGEkdHJlYXRtZW50ID09ICJPU0kiXSxdCiAgIyBkYXRhID0gYXBwbHkoZGF0YSwgTUFSR0lOID0gMiwgbWluX21heF9ub3JtYWxpemUpICU+JSBhcy5kYXRhLmZyYW1lKCkKICAKICBjb2xuYW1lcyhkYXRhKSA9IGMoIklGTmEiLCJUTkZhX05GS2IiLCJISUYiKQogIAoKICBwID0gZ2d0ZXJuKGRhdGEsZ2d0ZXJuOjphZXMoSUZOYSxUTkZhX05GS2IsSElGKSkgK2dlb21fcG9pbnQoKSsKICBnZ3RpdGxlKHBhc3RlKCJNb2RlbCIscGF0aWVudF9uYW1lKSkrCiAgdGhlbWVfdHJvcGljYWwoYmFzZV9zaXplPTE0KQogIAoKICBwX2xpc3RbW3BhdGllbnRfbmFtZV1dID0gcAoKfQoKYGBgCgoKYGBge3J9CiMgRGVzY3JpcHRpb24KbGlicmFyeShnZ3Rlcm4pCnBfbGlzdCA9IGxpc3QoKQoKZm9yIChwYXRpZW50X25hbWUgaW4gdW5pcXVlKHhlbm8kb3JpZy5pZGVudCkpIHsKICAjIHBhdGllbnRfbmFtZSA9ICIxMTkiCiAgcGF0aWVudF9kYXRhID0gc3Vic2V0KHhlbm8sc3Vic2V0ID0gb3JpZy5pZGVudCA9PSBwYXRpZW50X25hbWUpCiAgcGF0aHdheXNfbmFtZXMgPSBjKAogICAgIkhBTExNQVJLLUlOVEVSRkVST04tQUxQSEEtUkVTUE9OU0UiLAogICAgIkhBTExNQVJLLVRORkEtU0lHTkFMSU5HLVZJQS1ORktCIiwKICAgICJIQUxMTUFSSy1IWVBPWElBIgogICkKICAKICBEZWZhdWx0QXNzYXkocGF0aWVudF9kYXRhKSA9ICJzaXBzaWMiCiAgZGF0YSA9IEZldGNoRGF0YShvYmplY3QgPSBwYXRpZW50X2RhdGEsIHZhcnMgPSBjKHBhdGh3YXlzX25hbWVzKSkKICAjIGRhdGFbXSA8LSBkYXRhICU+JQogICMgICBtdXRhdGUoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfiBhcy5udW1lcmljKG1pbl9tYXhfbm9ybWFsaXplKC4pKSkpICAjIHNjYWxlIHBlciBwYXRod2F5CiAgZGF0YSR0cmVhdG1lbnQgPSBwYXRpZW50X2RhdGEkdHJlYXRtZW50CiAgY29sbmFtZXMoZGF0YSkgPSBjKCJJRk5hIiwiVE5GYV9ORktiIiwiSElGIiwidHJlYXRtZW50IikKICAKCiAgcCA9IGdndGVybihkYXRhLGdndGVybjo6YWVzKElGTmEsVE5GYV9ORktiLEhJRikpICsKZ2VvbV9wb2ludChnZ3Rlcm46OmFlcyhmaWxsPXRyZWF0bWVudCxzaGFwZT10cmVhdG1lbnQpLGNvbG9yPSdibGFjaycpICsKc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxLDIyKSxicmVha3MgPSBjKCJPU0kiKSkrCiAgICBnZ3RpdGxlKHBhc3RlKCJNb2RlbCIscGF0aWVudF9uYW1lKSkrCiAgdGhlbWVfdHJvcGljYWwoYmFzZV9zaXplPTE0KQogICAgCgogIHBfbGlzdFtbcGF0aWVudF9uYW1lXV0gPSBwCgp9CgpgYGAKYGBge3J9CiMgRGVzY3JpcHRpb24KVmlldyhwMSRkYXRhKQpwX2xpc3QKYGBgCgpgYGB7cn0KCiMgRGVzY3JpcHRpb24KZGYgPSBkYXRhLmZyYW1lKHg9YygwLjgsMC4wNikseT1jKDAuMiwwLjg3KSx6PWMoMC4xLDAuMDMpKQpsYWJGbmMgPC0gZnVuY3Rpb24oeCxkaWdpdHM9MikgZm9ybWF0KHJvdW5kKHVuaXF1ZSh4KSxkaWdpdHMpLGRpZ2l0cz1kaWdpdHMpCmJyZWFrcyA9IHNlcShmcm9tID0gMCwgdG8gPSAxLCBieSA9IDAuMSkKcDEgPSBnZ3Rlcm4oZGF0YT1kZixnZ3Rlcm46OmFlcyh4LHkseikpICsgZ2VvbV9wb2ludCgpKwogIHRoZW1lX3Ryb3BpY2FsKGJhc2Vfc2l6ZT0xNCkgKwogIHNjYWxlX1RfY29udGludW91cyhicmVha3M9dW5pcXVlKGRmJHkpLGxhYmVscyA9IGxhYkZuYyhkZiR5KSkgKwogIHNjYWxlX0xfY29udGludW91cyhicmVha3M9dW5pcXVlKGRmJHgpLGxhYmVscz1sYWJGbmMoZGYkeCkpICsKICBzY2FsZV9SX2NvbnRpbnVvdXMoYnJlYWtzPXVuaXF1ZShkZiR6KSxsYWJlbHM9bGFiRm5jKGRmJHkpKSAKCmNyZCA9IGNvb3JkX3Rlcm4oKQpkZgpkZWJ1Z29uY2UodGxyMnh5KQp0bHIyeHkoZGYsY3JkLHNjYWxlID0gRikKCgpkZWJ1Z29uY2UoY29vcmRfdGVybikKCiAgZ2dwbG90KGRhdGEgPSBGZWxkc3BhciwgbWFwcGluZyA9IGdndGVybjo6YWVzKEFiLEFuLE9yKSkgKyBjb29yZF90ZXJuKFRsaW0gID0gYygwLDAuMiksTGxpbSA9IGMoMCwwLjUpKQoKCmdndGVybihkYXRhPUZlbGRzcGFyLGdndGVybjo6YWVzKEFiLEFuLE9yKSkgKyAKICBnZW9tX3BvaW50KGdndGVybjo6YWVzKGZpbGw9RmVsZHNwYXIsc2hhcGU9RmVsZHNwYXIsc2l6ZT1QLkdwYSksY29sb3I9J2JsYWNrJykgKyAKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjEsMjIpLGJyZWFrcyA9IGMoIkFsa2FsYWkiKSkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CiMgcGxvdApkby5jYWxsKGdndGVybjo6Z3JpZC5hcnJhbmdlLGFyZ3MgPSBjKHBfbGlzdCxuY29sPTMpKQpgYGAKCgo=